package com.chuangjian.hire.sms.service.impl;

import com.chuangjian.hire.common.exceptionEnum.ApiExceptionEnum;
import com.chuangjian.hire.common.exption.ApiException;
import com.chuangjian.hire.sms.service.SmsCodeService;
import com.chuangjian.hire.sms.service.SmsService;
import com.chuangjian.hire.sms.service.SmsStore;
import com.chuangjian.hire.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@Transactional
public class SmsCodeServiceImpl implements SmsCodeService {

    @Resource
    SmsService smsService;

    @Resource
    SmsStore smsStore;

    @Override
    public String sendSmsCode(String mobile, Integer smsType, Map map) {
        String msgCode = smsStore.getVerifyCode(mobile, smsType);
        if (msgCode != null) {
            Long lastCodeTime = smsStore.getVerifyCodeTime(mobile, smsType);
            long time = System.currentTimeMillis() - lastCodeTime;
            if ((time / 1000) < 60L) {
                throw new ApiException(ApiExceptionEnum.MESSAGE_TO_MANY);
            }
        }
        msgCode = StringUtil.getRandomCodeA(5);
        //三分钟内有效
        long expireTime = 3 * 60;
        smsStore.storeVerifyCode(mobile, smsType, msgCode, expireTime);

        map.put("1", msgCode);

        // 生成发送模板
        smsService.sendSMS(mobile, smsType, map);
        return msgCode;
    }

    @Override
    public boolean verifySmsCode(String mobile, String msgCode, Integer smsType) {
        String verifyCodeDB = smsStore.getVerifyCode(mobile, smsType);
        return Objects.equals(msgCode, verifyCodeDB);
    }

    @Override
    public boolean deleteSmsCode(String mobile, Integer msgType) {
        return smsStore.deleteVerifyCode(mobile, msgType);
    }


    @Bean
    public SmsStore getSmsStore() {
        return new DefaultStoreImpl();
    }

    class DefaultStoreImpl implements SmsStore {

        @Resource
        private RedisTemplate<String, String> redisTemplate;

        @Override
        public boolean storeVerifyCode(String mobile, int smsType, String verifyCode, long expireTime) {
            String key = getKey(mobile, smsType);
            redisTemplate.opsForHash().put(key, "code", verifyCode);
            redisTemplate.opsForHash().put(key, "time", String.valueOf(System.currentTimeMillis()));
            return redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        }

        @Override
        public String getVerifyCode(String mobile, int smsType) {
            Map<Object, Object> map = redisTemplate.opsForHash().entries(getKey(mobile, smsType));
            return (String) map.get("code");
        }

        @Override
        public Long getVerifyCodeTime(String mobile, int smsType) {
            Map<Object, Object> map = redisTemplate.opsForHash().entries(getKey(mobile, smsType));
            return Long.valueOf((String) map.get("time")).longValue();
        }

        @Override
        public boolean deleteVerifyCode(String mobile, int smsType) {
            String key = getKey(mobile, smsType);
            return redisTemplate.delete(key);
        }

        public String getKey(String mobile, int smsType) {
            return "user_sms_flag_" + smsType + "_" + mobile;
        }
    }


}
